/*
基本功能完全,加密还没添加
感谢
Daniel J. Murphy的PasswordPump
https://github.com/seawarrior181/PasswordPump
很多代码都是抄他的,特别是EEPROM的读写
by:Metoo
2020年1月19日

由于我去弄stm32版本的了.
这个版本编译完已经占用96%的程序空间.
Arduino版本基本不会再更新了.
by:Metoo
2020年3月29日




许可
License
https://creativecommons.org/licenses/by-nc-sa/4.0/deed.zh

*/
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <SPI.h>
#include <EEPROM.h>
#include <Button2.h>
#include <Keyboard.h>
#include <Rotary.h>

#define SCREEN_WIDTH 128      // 屏幕宽度
#define SCREEN_HEIGHT 32      // 屏幕高度
#define OLED_RESET 4          // 屏幕重置按键
#define WHITE 1               //白色
#define BLACK 0               //黑色
#define SSD1306_I2C_ADDR 0x3C // 屏幕I2C地址
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

//---------------编码器引脚设置-------------
#define ROTARY_PINA 8
#define ROTARY_PINB 10
#define BUTTON_PIN 9
#define LONG_CLICK_LENGTH 500                        //长按持续时间
Rotary my_rotary = Rotary(ROTARY_PINA, ROTARY_PINB); //编码器
Button2 encoderButton = Button2(BUTTON_PIN);         //按键

//---------------其它设置-------------
#define BAUD_RATE 115200       //波特率
#define AUTO_LOCK_TIME 1800000 //自动锁定等待时间
unsigned long oldTime = 0;     //空闲运行时间

//----------------显示软件设置----------------
#define X10 0        //第一行X位置
#define Y10 0        //第一行y位置
#define X20 0        //第二行x位置
#define Y20 16       //第二行y位置(16是第一行用去的高度)
#define X_YES 116    //"是否"显示位置
#define Y_YES 20     //"是否"显示位置
#define ZH1_HIGH 16  //中文字体高度
#define ZH1_WIDTH 16 //中文字体宽度
#define ZH2_HIGH 12  //中文字体高度
#define ZH2_WIDTH 12 //中文字体宽度

//--------------25LC256---------------------
#define READ 0b00000011            //从选定地址开始的存储阵列读取数据
#define WRITE 0b00000010           //从所选地址开始将数据写入存储阵列
#define WRDI 0b00000100            //重置写使能锁存器（禁用写操作）
#define WREN 0b00000110            //设置写启用锁存器（启用写操作）
#define RDSR 0b00000101            //读取状态寄存器
#define WRSR 0b00000001            //写入状态寄存器
#define DATAOUT 16                 //MOSI
#define DATAIN 14                  //MISO
#define SPICLOCK 15                //sck
#define SLAVESELECT 10             //ss
#define MAX_AVAIL_ADDR 0x7FFF      //EEPROM最大地址
#define MIN_AVAIL_ADDR 0x0000      // EEPROM最小地址
#define EEPROM_BYTES_PER_PAGE 0X20 //页面大小,25LC256最大64

//---------------存储分配--------------------
#define ACCOUNT_SIZE EEPROM_BYTES_PER_PAGE  //名称占用空间
#define USERNAME_SIZE EEPROM_BYTES_PER_PAGE //账号占用空间
#define PASSWORD_SIZE EEPROM_BYTES_PER_PAGE //账户密码占用空间
#define REMARK_SIZE 0X1F                    //备注大小
#define MODE_SIZE 0x02                      //输出方式
#define IDs_SIZE 0x80                       //每个账户占用空间
#define IDs_MIN 0                           //最大254个账户,剩下128b用作存储设置及主密码
#define IDs_MAX 254
#define MASTER_PASSWORD_SIZE 0X40      //主密码64位
#define SET_READ_SERLAI_SIZE 0x02      //键盘输入设置
#define SET_SHOW_PASSWORD_SIZE 0x02    //显示密码设置
#define LOGIN_FAILURES_SIZE 0x01       //登录失败的标记
#define EEPROM_MARK_SIZE 0x20          //在eeprom上做标记以显示已初始化
#define INITIAL_MEMORY_STATE_BYTE 0xFF //初始化添入的数据
#define NULL_TERM 0x00                 //空数据
//--------------地址----------------------------
#define ACCOUNT_ADDR (IDs * IDs_SIZE)                                          //账户地址
#define USERNAME_ADDR (ACCOUNT_ADDR + ACCOUNT_SIZE)                            //用户名地址
#define PASSWORE_ADDR (USERNAME_ADDR + USERNAME_SIZE)                          //密码地址
#define REMARK_ADDR (PASSWORE_ADDR + PASSWORD_SIZE)                            //备注地址
#define MODE_ADDR (REMARK_ADDR + REMARK_SIZE)                                  //输出模式地址地址
#define MASTER_PASSWORD_ADDR (IDs_SIZE * (IDs_MAX + 1))                        //主密码62位
#define SET_READ_SERLAI_ADDR (MASTER_PASSWORD_ADDR + MASTER_PASSWORD_SIZE)     //键盘输入设置
#define SET_SHOW_PASSWORD_ADDR (SET_READ_SERLAI_ADDR + SET_SHOW_PASSWORD_SIZE) //显示密码设置
#define LOGIN_FAILURES_ADDR (SET_SHOW_PASSWORD_ADDR + LOGIN_FAILURES_SIZE)     //登录失败地址
#define EEPROM_MARK_ADDR (MAX_AVAIL_ADDR - EEPROM_MARK_SIZE)                   //EEPROM上标记地址

//---------------- SPI------------------------------

#define SPI_SS_PRIMARY PF4 // chip select primary (copy source)  (SPI)
#define SPI_SS_PRIMARY_PORT PORTF
#define SPI_SS_PRIMARY_PIN PINF
#define SPI_SS_PRIMARY_DDR DDRF
#define SPI_SS_SECONDARY PF5        // chip select seconday (copy target)  (SPI)
#define SPI_SS_SECONDARY_PORT PORTF //
#define SPI_SS_SECONDARY_PIN PINF   //
#define SPI_SS_SECONDARY_DDR DDRF   //
#define SPI_MOSI PB2                // mosi (SPI)
#define SPI_MOSI_PORT PORTB
#define SPI_MOSI_PIN PINB
#define SPI_MOSI_DDR DDRB
#define SPI_MISO PB3 // miso (SPI)
#define SPI_MISO_PORT PORTB
#define SPI_MISO_PIN PINB
#define SPI_MISO_DDR DDRB
#define SPI_SCK PB1 // clock (SPI)
#define SPI_SCK_PORT PORTB
#define SPI_SCK_PIN PINB
#define SPI_SCK_DDR DDRB                                                          //
#define SLAVE_PRIMARY_SELECT SPI_SS_PRIMARY_PORT &= ~(1 << SPI_SS_PRIMARY);       //选择主芯片
#define SLAVE_PRIMARY_DESELECT SPI_SS_PRIMARY_PORT |= (1 << SPI_SS_PRIMARY)       //释放主芯片
#define SLAVE_SECONDARY_SELECT SPI_SS_SECONDARY_PORT &= ~(1 << SPI_SS_SECONDARY); //选择次芯片
#define SLAVE_SECONDARY_DESELECT SPI_SS_SECONDARY_PORT |= (1 << SPI_SS_SECONDARY) //释放次芯片

#define EEPROM_WRITE_IN_PROGRESS 0
#define EEPROM_WRITE_ENABLE_LATCH 1
#define EEPROM_BLOCK_PROTECT_0 2
#define EEPROM_BLOCK_PROTECT_1 3

//-------------------事件--------------------
#define EVENT_NONE 0         // 用于切换上一个事件以避免无限循环
#define EVENT_SINGLE_CLICK 1 // 单击旋转编码器
#define EVENT_LONG_CLICK 2   // 按住旋转编码器上的按钮1秒钟以上（？）（直接从库中的默认值更改）
#define EVENT_ROTATE_CW 3    // 顺时针旋转旋转编码器
#define EVENT_ROTATE_CC 4    // 逆时针旋转旋转编码器
volatile uint8_t event = EVENT_NONE;
//----------------------------------------------------

bool LOCK = true;         //解锁标记
bool confirmMark = false; //确认标记,显示"是,否",或是"开,关"

//-------------------主菜单设置-----------------
#define MAIN_MENU_MIN 1
#define MAIN_MENU_MAX 8 // 主菜单中的选择数量
#define MENU_ACCOUNT 1
#define MENU_ACCOUNT_LIST 11
#define MENU_ID 111
#define MENU_LOGOUT 2
#define MENU_READ_SERLAI 3
#define MENU_SHOW_PASSWORD 4
#define MENU_BACKUP_EEPROM 5
#define MENU_BACKUP_ON 51
#define MENU_BACKUP_END 52
#define MENU_BACKUP_FILE 6
#define MENU_RESTORE_BACKUP 7
#define MENU_RESTORE_ON 71
#define MENU_RESTORE_END 72
#define MENU_FACTORY_RESET 8
#define MENU_SET_FACTORY_RESET 81
#define MENU_FORMAT 82
#define MENU_FORMAT_COMPLETE 83
#define MENU_WELCOME 9
#define EDIT_MODE 0

#define CARD_MENU_MIN 0
#define CARD_MENU_MAX 9
#define CARD_MENU_Delete_Acct 0         //	删除账户
#define CARD_MENU_Edit_Indicate_Style 1 //	编辑发送模式
#define CARD_MENU_Edit_Remark 2         //	编辑备注
#define CARD_MENU_Edit_Password 3       //	编辑密码
#define CARD_MENU_Edit_Username 4       //	编辑用户名
#define CARD_MENU_Edit_Creds 5          //	编辑标题
#define CARD_MENU_Send_User_Pass 6      //	发送用户名及密码
#define CARD_MENU_Send_Username 7       //	发送用户名
#define CARD_MENU_Send_Password 8       //	发送密码
#define CARD_MENU_Send_Remark 9         //	编辑备注
char menuID;                            //初始菜单页面
char cardmenuID = CARD_MENU_Send_User_Pass;
int IDs = 0;

//------------------EEPROM软件------------
bool primaryFlag = true; //主次芯片选择
bool copyStart = false;  //串口输入识别
char buffer[EEPROM_BYTES_PER_PAGE];
char acconut_buffer[EEPROM_BYTES_PER_PAGE];

char masterPassword[MASTER_PASSWORD_SIZE];                       //从EEPROM读取的主密码
char accountName[ACCOUNT_SIZE];                                  // 账户名称缓存
char username[USERNAME_SIZE];                                    // 用户名缓存
char password[PASSWORD_SIZE];                                    // 密码缓存
char remark[REMARK_SIZE];                                        // 备注缓存
uint8_t mode[MODE_SIZE];                                         //输出模式
uint8_t showPassword[SET_SHOW_PASSWORD_SIZE];                    //密码显示开关
uint8_t readSerial[SET_READ_SERLAI_SIZE];                        //串口开关
char masterPasswordbuffer[MASTER_PASSWORD_SIZE];                 //输入的密码
char eepromMark[EEPROM_MARK_SIZE];                               //从EEPROM读取到内存的标记
uint8_t loginFailures[LOGIN_FAILURES_SIZE];                      //登录失败次数
char Mark[EEPROM_MARK_SIZE] = "Made By Metoo in China 20-02-02"; //数据不能写满,字符串需要一个额外的单元存储结束符\\0

//----------屏幕输入键盘设置----------------
#define ALLCHARS_SIZE 94
#define NUMBER_SIZE 10
const char allChars[ALLCHARS_SIZE] = // used to edit text via rotary encoder (164 bytes)
    " /?><,:';|}{][+_)(*&^%$#!~=\-@. 0123456789AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz";
uint8_t allChars_position = 39; //字符输入时的数组指针
uint8_t allChars_enterPosition = 0;
String comdata = ""; //串口读取的数据
uint8_t CC = 0;      //串口输入循环标记

static const uint8_t PROGMEM welcome_128x32[] = {
    0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x18, 0x00, 0x38, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x18,
    0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x0C, 0x38, 0x00, 0x70, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x78, 0x00, 0x70, 0x00, 0x07,
    0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x78,
    0x00, 0xE0, 0x1E, 0x1F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x38, 0xF8, 0x38, 0xFC, 0xFF, 0x3E, 0x70, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x39, 0xF0, 0x79, 0xF8, 0xFF, 0x78,
    0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x69, 0xB0,
    0xF9, 0xF1, 0xE7, 0xF0, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0,
    0x00, 0x00, 0x79, 0xB1, 0xB7, 0xC1, 0xE7, 0xE1, 0xC0, 0x00, 0x00, 0x00,
    0x00, 0x03, 0xC1, 0x80, 0x00, 0x00, 0xDB, 0xB3, 0x67, 0x83, 0xCF, 0xC7,
    0x80, 0x0F, 0xC7, 0xC7, 0xFF, 0x8E, 0xE3, 0x00, 0x00, 0x00, 0xDF, 0x33,
    0xC1, 0x83, 0xCD, 0xCF, 0x00, 0x1D, 0xC3, 0x0E, 0xC1, 0x98, 0xE2, 0x00,
    0x00, 0x01, 0x9E, 0x77, 0x83, 0x87, 0xBC, 0xFF, 0x00, 0x31, 0xC2, 0x18,
    0xC1, 0x10, 0x66, 0x00, 0x00, 0x03, 0x9E, 0x37, 0x03, 0x9F, 0xF8, 0xFC,
    0x00, 0x61, 0x8C, 0x31, 0xC0, 0x30, 0x7C, 0x00, 0x00, 0x03, 0x1C, 0x36,
    0x0B, 0xFB, 0xF0, 0x00, 0x00, 0x63, 0x90, 0x21, 0xC0, 0x30, 0x78, 0x00,
    0x00, 0x07, 0x1C, 0x36, 0x39, 0xF1, 0xC0, 0x00, 0x00, 0x73, 0xA0, 0x61,
    0x84, 0x30, 0x78, 0x00, 0x00, 0x06, 0x1C, 0x77, 0xF0, 0xE0, 0x00, 0x00,
    0x00, 0x03, 0xE0, 0x63, 0xFC, 0x10, 0x70, 0x00, 0x00, 0x0E, 0x1E, 0x33,
    0xE0, 0x00, 0x00, 0x00, 0x00, 0x03, 0x60, 0x63, 0x8C, 0x00, 0x70, 0x00,
    0x00, 0x0C, 0x3E, 0x30, 0x80, 0x00, 0x00, 0x00, 0x00, 0x07, 0x70, 0x33,
    0x80, 0x00, 0x70, 0x00, 0x00, 0x1C, 0x3E, 0x10, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x06, 0x30, 0x03, 0x00, 0x00, 0x60, 0x00, 0x00, 0x18, 0x0C, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x30, 0x07, 0x03, 0x00, 0xE0, 0x00,
    0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x38, 0x06,
    0x03, 0x00, 0xE0, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x0E, 0x18, 0x0F, 0xF3, 0x01, 0xE0, 0x00, 0x00, 0x70, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x18, 0x3F, 0xFE, 0x03, 0xF8, 0x00,
    0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x0C, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x70, 0x00, 0x00, 0x00, 0x00,
    0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xE0,
    0x00, 0x00, 0x00, 0x00, 0x01, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"主页.bmp",0*/
    /* (128 X 32 )*/
};
static const uint8_t PROGMEM mi_16x16[] = {
    0x02, 0x00, 0x01, 0x00, 0x7F, 0xFE, 0x40, 0x02, 0x82, 0x24, 0x09, 0x40,
    0x28, 0x88, 0x4B, 0x14, 0x1C, 0x10, 0xE7, 0xF0, 0x01, 0x00, 0x21, 0x08,
    0x21, 0x08, 0x21, 0x08, 0x3F, 0xF8, 0x00, 0x08, /*"密",2*/
    /* (16 X 16 , 宋体 )*/
};
static const uint8_t PROGMEM ma_16x16[] = {
    0x00, 0x00, 0x01, 0xF8, 0xFC, 0x08, 0x10, 0x08, 0x10, 0x88, 0x20, 0x88,
    0x3C, 0x88, 0x64, 0xFE, 0x64, 0x02, 0xA4, 0x02, 0x24, 0x02, 0x25, 0xFA,
    0x3C, 0x02, 0x24, 0x02, 0x20, 0x14, 0x00, 0x08, /*"码",1*/
    /* (16 X 16 , 宋体 )*/
};
static const uint8_t PROGMEM zhu_16x16[] = {
    0x00, 0x80, 0x20, 0x40, 0x10, 0x00, 0x17, 0xFC, 0x80, 0x40, 0x40, 0x40,
    0x40, 0x40, 0x10, 0x40, 0x13, 0xFC, 0x20, 0x40, 0xE0, 0x40, 0x20, 0x40,
    0x20, 0x40, 0x20, 0x40, 0x2F, 0xFE, 0x00, 0x00, /*"注",0*/
    /* (16 X 16 , 宋体 )*/
};
static const uint8_t PROGMEM xiao_16x16[] = {
    0x10, 0x20, 0x11, 0x24, 0x3C, 0xA4, 0x20, 0xA8, 0x40, 0x20, 0xBD, 0xFC,
    0x11, 0x04, 0x11, 0x04, 0xFD, 0xFC, 0x11, 0x04, 0x11, 0x04, 0x11, 0xFC,
    0x15, 0x04, 0x19, 0x04, 0x11, 0x14, 0x01, 0x08, /*"销",1*/
    /* (16 X 16 , 宋体 )*/
};
static const uint8_t PROGMEM bei_16x16[] = {
    0x04, 0x00, 0x04, 0x00, 0x0F, 0xF0, 0x18, 0x20, 0x64, 0x40, 0x03, 0x80,
    0x1C, 0x70, 0xE0, 0x0E, 0x1F, 0xF0, 0x11, 0x10, 0x11, 0x10, 0x1F, 0xF0,
    0x11, 0x10, 0x11, 0x10, 0x1F, 0xF0, 0x10, 0x10, /*"备",0*/
    /* (16 X 16 , 宋体 )*/
};
static const uint8_t PROGMEM fen_16x16[] = {
    0x08, 0x10, 0x08, 0x90, 0x08, 0x90, 0x10, 0x88, 0x11, 0x08, 0x31, 0x04,
    0x32, 0x04, 0x55, 0xFA, 0x90, 0x88, 0x10, 0x88, 0x10, 0x88, 0x10, 0x88,
    0x11, 0x08, 0x11, 0x08, 0x12, 0x28, 0x14, 0x10, /*"份",1*/
    /* (16 X 16 , 宋体 )*/
};
static const uint8_t PROGMEM hui_16x16[] = {
    0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0x13, 0xFE, 0x18, 0x80, 0x54, 0x90,
    0x50, 0x90, 0x51, 0x12, 0x91, 0x52, 0x11, 0x54, 0x12, 0x90, 0x12, 0x28,
    0x14, 0x28, 0x10, 0x44, 0x10, 0x84, 0x11, 0x02, /*"恢",0*/
    /* (16 X 16 , 宋体 )*/
};
static const uint8_t PROGMEM fu_16x16[] = {
    0x10, 0x00, 0x10, 0x00, 0x1F, 0xFC, 0x20, 0x00, 0x5F, 0xF0, 0x90, 0x10,
    0x1F, 0xF0, 0x10, 0x10, 0x1F, 0xF0, 0x04, 0x00, 0x0F, 0xF0, 0x18, 0x20,
    0x64, 0x40, 0x03, 0x80, 0x1C, 0x70, 0xE0, 0x0E, /*"复",1*/
    /* (16 X 16 , 宋体 )*/
};
static const uint8_t PROGMEM chuchang1_16x16[] = {
    0x01, 0x00, 0x01, 0x00, 0x21, 0x08, 0x21, 0x08, 0x21, 0x08, 0x21, 0x08,
    0x3F, 0xF8, 0x01, 0x08, 0x01, 0x00, 0x01, 0x00, 0x41, 0x04, 0x41, 0x04,
    0x41, 0x04, 0x41, 0x04, 0x7F, 0xFC, 0x00, 0x04, /*"出",0*/
    /* (16 X 16 , 宋体 )*/
};
static const uint8_t PROGMEM chuchang2_16x16[] = {
    0x00, 0x00, 0x3F, 0xFE, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00,
    0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00,
    0x20, 0x00, 0x40, 0x00, 0x40, 0x00, 0x80, 0x00, /*"厂",1*/
    /* (16 X 16 , 宋体 )*/
};
static const uint8_t PROGMEM xian_16x16[] = {
    0x00, 0x00, 0x1F, 0xF0, 0x10, 0x10, 0x10, 0x10, 0x1F, 0xF0, 0x10, 0x10,
    0x10, 0x10, 0x1F, 0xF0, 0x04, 0x40, 0x44, 0x44, 0x24, 0x44, 0x14, 0x48,
    0x14, 0x50, 0x04, 0x40, 0xFF, 0xFE, 0x00, 0x00, /*"显",0*/
    /* (16 X 16 , 宋体 )*/
};
static const uint8_t PROGMEM shi_16x16[] = {
    0x00, 0x00, 0x3F, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0xFF, 0xFE, 0x01, 0x00, 0x01, 0x00, 0x11, 0x10, 0x11, 0x08, 0x21, 0x04,
    0x41, 0x02, 0x81, 0x02, 0x05, 0x00, 0x02, 0x00, /*"示",1*/
    /* (16 X 16 , 宋体 )*/
};
static const uint8_t PROGMEM chuan_16x16[] = {
    0x01, 0x00, 0x01, 0x00, 0x3F, 0xF8, 0x21, 0x08, 0x21, 0x08, 0x3F, 0xF8,
    0x01, 0x00, 0x01, 0x00, 0x7F, 0xFC, 0x41, 0x04, 0x41, 0x04, 0x7F, 0xFC,
    0x41, 0x04, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, /*"串",0*/
    /* (16 X 16 , 宋体 )*/
};
static const uint8_t PROGMEM kou_16x16[] = {
    0x00, 0x00, 0x00, 0x00, 0x3F, 0xF8, 0x20, 0x08, 0x20, 0x08, 0x20, 0x08,
    0x20, 0x08, 0x20, 0x08, 0x20, 0x08, 0x20, 0x08, 0x20, 0x08, 0x20, 0x08,
    0x20, 0x08, 0x3F, 0xF8, 0x20, 0x08, 0x00, 0x00, /*"口",1*/
    /* (16 X 16 , 宋体 )*/
};
static const uint8_t PROGMEM zhang_16x16[] = {
    0x00, 0x80, 0x7C, 0x84, 0x44, 0x84, 0x54, 0x88, 0x54, 0x90, 0x54, 0xA0,
    0x54, 0x80, 0x55, 0xFE, 0x54, 0xA0, 0x54, 0xA0, 0x54, 0x90, 0x10, 0x90,
    0x28, 0x88, 0x24, 0xA4, 0x44, 0xC2, 0x80, 0x80, /*"账",0*/
    /* (16 X 16 , 宋体 )*/
};
static const uint8_t PROGMEM hu_16x16[] = {
    0x02, 0x00, 0x01, 0x00, 0x01, 0x00, 0x1F, 0xF8, 0x10, 0x08, 0x10, 0x08,
    0x10, 0x08, 0x10, 0x08, 0x1F, 0xF8, 0x10, 0x08, 0x10, 0x00, 0x10, 0x00,
    0x10, 0x00, 0x20, 0x00, 0x20, 0x00, 0x40, 0x00, /*"户",1*/
    /* (16 X 16 , 宋体 )*/
};
static const uint8_t PROGMEM dao_16x16[] = {
    0x00, 0x04, 0xFF, 0x84, 0x08, 0x04, 0x10, 0x24, 0x22, 0x24, 0x41, 0x24,
    0xFF, 0xA4, 0x08, 0xA4, 0x08, 0x24, 0x08, 0x24, 0x7F, 0x24, 0x08, 0x24,
    0x08, 0x04, 0x0F, 0x84, 0xF8, 0x14, 0x40, 0x08, /*"到",0*/
    /* (16 X 16 , 宋体 )*/
};
static const uint8_t PROGMEM zhong_16x16[] = {
    0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x3F, 0xF8, 0x21, 0x08,
    0x21, 0x08, 0x21, 0x08, 0x21, 0x08, 0x21, 0x08, 0x3F, 0xF8, 0x21, 0x08,
    0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, /*"中",0*/
    /* (16 X 16 , 宋体 )*/
};
static const uint8_t PROGMEM wan_16x16[] = {
    0x02, 0x00, 0x01, 0x00, 0x7F, 0xFE, 0x40, 0x02, 0x80, 0x04, 0x1F, 0xF0,
    0x00, 0x00, 0x00, 0x00, 0x7F, 0xFC, 0x04, 0x40, 0x04, 0x40, 0x04, 0x40,
    0x08, 0x44, 0x08, 0x44, 0x10, 0x44, 0x60, 0x3C, /*"完",0*/
    /* (16 X 16 , 宋体 )*/
};
static const uint8_t PROGMEM cheng_16x16[] = {
    0x00, 0x50, 0x00, 0x48, 0x00, 0x40, 0x3F, 0xFE, 0x20, 0x40, 0x20, 0x40,
    0x20, 0x44, 0x3E, 0x44, 0x22, 0x44, 0x22, 0x28, 0x22, 0x28, 0x22, 0x12,
    0x2A, 0x32, 0x44, 0x4A, 0x40, 0x86, 0x81, 0x02, /*"成",1*/
    /* (16 X 16 , 宋体 )*/
};
static const uint8_t PROGMEM kong_16x16[] = {
    0x02, 0x00, 0x01, 0x00, 0x7F, 0xFE, 0x40, 0x02, 0x88, 0x24, 0x10, 0x10,
    0x20, 0x08, 0x00, 0x00, 0x1F, 0xF0, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
    0x01, 0x00, 0x01, 0x00, 0x7F, 0xFC, 0x00, 0x00, /*"空",0*/
    /* (16 X 16 , 宋体 )*/
};
static const uint8_t PROGMEM kai_12x12[] = {
    0x00, 0x00, 0x7F, 0xC0, 0x11, 0x00, 0x11, 0x00, 0x11, 0x00, 0x11, 0x00,
    0xFF, 0xE0, 0x11, 0x00, 0x11, 0x00, 0x21, 0x00, 0x21, 0x00, 0x41, 0x00, /*"开",0*/
    // /* (12 X 12 , 宋体 )*/
};
static const uint8_t PROGMEM guan_12x12[] = {
    0x20, 0x80, 0x11, 0x00, 0x00, 0x00, 0x7F, 0xC0, 0x04, 0x00, 0x04, 0x00,
    0xFF, 0xE0, 0x04, 0x00, 0x0A, 0x00, 0x11, 0x00, 0x20, 0x80, 0xC0, 0x60, /*"关",1*/
    /* (12 X 12 , 宋体 )*/
};
static const uint8_t PROGMEM yes_12x12[] = {
    0x3F, 0x80, 0x20, 0x80, 0x3F, 0x80, 0x20, 0x80, 0x3F, 0x80, 0x00, 0x00,
    0xFF, 0xE0, 0x04, 0x00, 0x27, 0xC0, 0x24, 0x00, 0x54, 0x00, 0x8F, 0xE0, /*"是",0*/
    /* (12 X 12 , 宋体 )*/
};
static const uint8_t PROGMEM no_12x12[] = {
    0xFF, 0xE0, 0x04, 0x00, 0x0D, 0x80, 0x34, 0x40, 0xC4, 0x20, 0x04, 0x00,
    0x00, 0x00, 0x7F, 0xC0, 0x40, 0x40, 0x40, 0x40, 0x7F, 0xC0, 0x40, 0x40, /*"否",1*/
    /* (12 X 12 , 宋体 )*/
};
static const uint8_t PROGMEM shan_12x12[] = {
    0x00, 0x20, 0xEE, 0x20, 0xAA, 0xA0, 0xAA, 0xA0, 0xAA, 0xA0, 0xFF, 0xA0,
    0xAA, 0xA0, 0xAA, 0xA0, 0xAA, 0xA0, 0xAA, 0x20, 0xAA, 0x20, 0x66, 0x60, /*"删",0*/
    /* (12 X 12 , 宋体 )*/};
static const uint8_t PROGMEM chu_12x12[] = {
    0x01, 0x00, 0xE2, 0x80, 0xA4, 0x40, 0xA8, 0x20, 0xC7, 0xC0, 0xC1, 0x00,
    0xAF, 0xE0, 0xA1, 0x00, 0xA5, 0x40, 0xC9, 0x20, 0x91, 0x20, 0x83, 0x00, /*"除",1*/
    /* (12 X 12 , 宋体 )*/};
static const uint8_t PROGMEM zhang_12x12[] = {
    0x02, 0x00, 0xFA, 0x40, 0x8A, 0x80, 0xAB, 0x00, 0xAA, 0x00, 0xAF, 0xE0,
    0xAA, 0x80, 0xAA, 0x80, 0xAA, 0x40, 0x22, 0x40, 0x53, 0x20, 0x8A, 0x00, /*"账",2*/
    /* (12 X 12 , 宋体 )*/};
static const uint8_t PROGMEM hu_12x12[] = {
    0x04, 0x00, 0x02, 0x00, 0x3F, 0xE0, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
    0x3F, 0xE0, 0x20, 0x20, 0x20, 0x00, 0x40, 0x00, 0x40, 0x00, 0x80, 0x00, /*"户",3*/
    /* (12 X 12 , 宋体 )*/};
static const uint8_t PROGMEM bian_12x12[] = {
    0x41, 0x00, 0x4F, 0xE0, 0x88, 0x20, 0xAF, 0xE0, 0xC8, 0x00, 0x4F, 0xE0,
    0x8A, 0xA0, 0xDA, 0xA0, 0x0F, 0xE0, 0x2A, 0xA0, 0xCA, 0xA0, 0x08, 0x60, /*"编",4*/
    /* (12 X 12 , 宋体 )*/};
static const uint8_t PROGMEM ji_12x12[] = {
    0x27, 0xC0, 0x24, 0x40, 0xF7, 0xC0, 0x40, 0x00, 0x6F, 0xE0, 0xA4, 0x40,
    0xF7, 0xC0, 0x24, 0x40, 0x37, 0xC0, 0xE4, 0x60, 0x2F, 0xC0, 0x20, 0x40, /*"辑",5*/
    /* (12 X 12 , 宋体 )*/};
static const uint8_t PROGMEM fa_12x12[] = {
    0x09, 0x00, 0x88, 0x80, 0x88, 0x00, 0xFF, 0xE0, 0x10, 0x00, 0x10, 0x00,
    0x1F, 0x80, 0x28, 0x80, 0x25, 0x00, 0x42, 0x00, 0x8D, 0x80, 0x30, 0x60, /*"发",6*/
    /* (12 X 12 , 宋体 )*/};
static const uint8_t PROGMEM song_12x12[] = {
    0x88, 0x80, 0x45, 0x00, 0x00, 0x00, 0x1F, 0xC0, 0xC2, 0x00, 0x42, 0x00,
    0x7F, 0xE0, 0x42, 0x00, 0x45, 0x00, 0x48, 0x80, 0x50, 0x40, 0xBF, 0xE0, /*"送",7*/
    /* (12 X 12 , 宋体 )*/};
static const uint8_t PROGMEM mo_12x12[] = {
    0x22, 0x80, 0x2F, 0xE0, 0x22, 0x80, 0xF7, 0xC0, 0x24, 0x40, 0x67, 0xC0,
    0x74, 0x40, 0xA7, 0xC0, 0x21, 0x00, 0x2F, 0xE0, 0x22, 0x80, 0x2C, 0x60, /*"模",8*/
    /* (12 X 12 , 宋体 )*/};
static const uint8_t PROGMEM shi_12x12[] = {
    0x01, 0x40, 0x01, 0x20, 0x01, 0x00, 0xFF, 0xE0, 0x01, 0x00, 0x01, 0x00,
    0x7D, 0x00, 0x11, 0x00, 0x10, 0x80, 0x10, 0xA0, 0x1E, 0x60, 0xE0, 0x20, /*"式",9*/
    /* (12 X 12 , 宋体 )*/};
static const uint8_t PROGMEM bei_12x12[] = {
    0x10, 0x00, 0x3F, 0x80, 0x51, 0x00, 0x0E, 0x00, 0x31, 0x80, 0xC0, 0x60,
    0x3F, 0x80, 0x24, 0x80, 0x3F, 0x80, 0x24, 0x80, 0x3F, 0x80, 0x20, 0x80, /*"备",10*/
    /* (12 X 12 , 宋体 )*/};
static const uint8_t PROGMEM zhu_12x12[] = {
    0x04, 0x00, 0x82, 0x00, 0x40, 0x00, 0x1F, 0xC0, 0x02, 0x00, 0x82, 0x00,
    0x42, 0x00, 0x1F, 0xC0, 0x02, 0x00, 0x42, 0x00, 0x82, 0x00, 0x3F, 0xE0, /*"注",11*/
    /* (12 X 12 , 宋体 )*/};
static const uint8_t PROGMEM mi_12x12[] = {
    0x04, 0x00, 0xFF, 0xE0, 0x88, 0x20, 0x05, 0x00, 0x52, 0x40, 0x54, 0xA0,
    0x8F, 0xA0, 0x30, 0x00, 0x04, 0x00, 0x44, 0x40, 0x44, 0x40, 0x7F, 0xC0, /*"密",12*/
    /* (12 X 12 , 宋体 )*/};
static const uint8_t PROGMEM ma_12x12[] = {
    0x0F, 0xC0, 0xF0, 0x40, 0x24, 0x40, 0x24, 0x40, 0x44, 0x40, 0x77, 0xE0,
    0xD0, 0x20, 0x50, 0x20, 0x5F, 0xA0, 0x70, 0x20, 0x50, 0x20, 0x00, 0xC0, /*"码",13*/
    /* (12 X 12 , 宋体 )*/};
static const uint8_t PROGMEM yong_12x12[] = {
    0x00, 0x00, 0x7F, 0xC0, 0x44, 0x40, 0x44, 0x40, 0x7F, 0xC0, 0x44, 0x40,
    0x44, 0x40, 0x7F, 0xC0, 0x44, 0x40, 0x44, 0x40, 0x44, 0x40, 0x81, 0xC0, /*"用",14*/
    /* (12 X 12 , 宋体 )*/};
static const uint8_t PROGMEM ming_12x12[] = {
    0x08, 0x00, 0x08, 0x00, 0x1F, 0xC0, 0x20, 0x40, 0x50, 0x80, 0x0B, 0x00,
    0x0C, 0x00, 0x3F, 0xE0, 0xD0, 0x20, 0x10, 0x20, 0x1F, 0xE0, 0x10, 0x20, /*"名",16*/
    /* (12 X 12 , 宋体 )*/};
static const uint8_t PROGMEM biao_12x12[] = {
    0x20, 0x00, 0x27, 0xC0, 0x20, 0x00, 0xF0, 0x00, 0x2F, 0xE0, 0x61, 0x00,
    0x71, 0x00, 0xA5, 0x40, 0x25, 0x20, 0x29, 0x20, 0x21, 0x00, 0x23, 0x00, /*"标",17*/
    /* (12 X 12 , 宋体 )*/};
static const uint8_t PROGMEM ti_12x12[] = {
    0x7B, 0xE0, 0x48, 0x80, 0x79, 0x00, 0x4B, 0xE0, 0x7A, 0x20, 0x02, 0xA0,
    0xFE, 0xA0, 0x12, 0xA0, 0x59, 0x40, 0x52, 0x20, 0x50, 0x00, 0xBF, 0xE0, /*"题",18*/
    /* (12 X 12 , 宋体 )*/};
static const uint8_t PROGMEM he_12x12[] = {
    0x08, 0x00, 0x70, 0x00, 0x13, 0xE0, 0x12, 0x20, 0xFE, 0x20, 0x12, 0x20,
    0x3A, 0x20, 0x56, 0x20, 0x92, 0x20, 0x13, 0xE0, 0x12, 0x20, 0x10, 0x00, /*"和",0*/
    /* (12 X 12 , 宋体 )*/
};

void setup()
{
    initSPI();
    Serial.begin(BAUD_RATE);

    //屏幕
    display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
    display.clearDisplay();
    display.setRotation(2); //旋转屏幕
    display.drawBitmap(0, 0, welcome_128x32, 128, 32, WHITE);
    display.display();

    Keyboard.begin();

    //编码器
    my_rotary.begin();
    PCICR |= (1 << PCIE0);
    PCMSK0 |= (1 << PCINT6) | (1 << PCINT4); //PCINT6 = D10,PCINT4 = D8.详情看芯片手册
    sei();
    encoderButton.setReleasedHandler(buttonReleasedHandler); //编码器按钮

    menuID = EDIT_MODE;

    //读取EEPROM上的设置
    loginFailures[0] = read_eeprom_byte(LOGIN_FAILURES_ADDR, primaryFlag); //格式化后会填满255,如果这个标签=255,那就表明密码还没有设置
    readSerial[0] = read_eeprom_byte(SET_READ_SERLAI_ADDR, primaryFlag);
    showPassword[0] = read_eeprom_byte(SET_SHOW_PASSWORD_ADDR, primaryFlag);
    read_eeprom_array(EEPROM_MARK_ADDR, eepromMark, EEPROM_MARK_SIZE, primaryFlag);
    if (strcmp(eepromMark, Mark)) //没有标记则恢复出厂设置
    {
        InitializeEEProm();
    }
}

void loop()
{
    display.clearDisplay();
    encoderButton.loop();
    autolock();
    menu();
    loginFailuresMAX();
    SerialRead();
}

ISR(PCINT0_vect) //编码器
{
    unsigned char result = my_rotary.process();
    if (result)
    {
        if (result == DIR_CW)
        {
            event = EVENT_ROTATE_CW;
        }
        else
        {
            event = EVENT_ROTATE_CC;
        }
    }
}

void autolock()
{
    if (millis() - oldTime > AUTO_LOCK_TIME)
    {
        out();
    }
}

void out()
{
    display.clearDisplay();
    LOCK = true;
    memset(masterPasswordbuffer, 0, MASTER_PASSWORD_SIZE);
    memset(masterPassword, 0, MASTER_PASSWORD_SIZE);
    allChars_position = 39;
    allChars_enterPosition = 0;
    menuID = MENU_WELCOME;
}

void clearbuf()
{
    memset(acconut_buffer, 0, PASSWORD_SIZE);
    allChars_position = 39;
    allChars_enterPosition = 0;
}

void buttonReleasedHandler(Button2 &btn)
{
    if (btn.wasPressedFor() > LONG_CLICK_LENGTH)
    {
        event = EVENT_LONG_CLICK;
    }
    else
    {
        event = EVENT_SINGLE_CLICK;
    }
}

void loginFailuresMAX()
{
    if (loginFailures[0] == 10)
    {
        InitializeEEProm();
    }
}

void SerialRead()
{
    while (Serial.available() > 0)
    {
        comdata += char(Serial.read());
        delay(2);
    }

    if (comdata.length() > 0)
    {
        strcpy(buffer, comdata.c_str());
        if (strcmp(buffer, Mark) == 0)
        {
            copyStart = !copyStart;
            CC = 0;
            if (copyStart)
            {
                Serial.println("Reception started");
            }
            else if (!copyStart)
            {
                Serial.println("End of reception");
            }
        }
        if (copyStart && readSerial[0])
        {
            if (CC == 1)
            {
                IDs = atoi(buffer);
            }
            if (CC == 2)
            {
                write_eeprom_array(ACCOUNT_ADDR, buffer, ACCOUNT_SIZE, primaryFlag);
            }
            if (CC == 3)
            {
                write_eeprom_array(USERNAME_ADDR, buffer, USERNAME_SIZE, primaryFlag);
            }
            if (CC == 4)
            {
                write_eeprom_array(PASSWORE_ADDR, buffer, PASSWORD_SIZE, primaryFlag);
            }
            if (CC == 5)
            {
                write_eeprom_array(REMARK_ADDR, buffer, REMARK_SIZE, primaryFlag);
                CC = 0;
            }
            CC++;
        }
    }
    comdata = "";
}
//////////////////////////////////////////////////////////////////////////////////////
void initSPI(void)
{
    SPI_SS_PRIMARY_DDR |= (1 << SPI_SS_PRIMARY);  // 设置主EEprom芯片的SS输出
    SPI_SS_PRIMARY_DDR |= (1 << SPI_SS_PRIMARY);  // 设置主EEprom芯片的SS输出
    SPI_SS_PRIMARY_PORT |= (1 << SPI_SS_PRIMARY); // 开始未选择（high）

    SPI_SS_SECONDARY_DDR |= (1 << SPI_SS_SECONDARY);  // 设置SS输出以备份EEprom芯片
    SPI_SS_SECONDARY_DDR |= (1 << SPI_SS_SECONDARY);  // 设置SS输出以备份EEprom芯片
    SPI_SS_SECONDARY_PORT |= (1 << SPI_SS_SECONDARY); // 开始未选择（high）

    SPI_MOSI_DDR |= (1 << SPI_MOSI);  // 在MOSI上输出
    SPI_MISO_PORT |= (1 << SPI_MISO); // 拉起MISO
    SPI_SCK_DDR |= (1 << SPI_SCK);    // 在SCK上输出
    SPCR |= (1 << SPR0);
    SPCR |= (1 << SPR1);
    SPCR |= (1 << MSTR);
    SPCR |= (1 << SPE);
}
void ChipSelect(bool primaryFlag)
{
    if (primaryFlag)
    {
        SLAVE_PRIMARY_SELECT;
    }
    else
    {
        SLAVE_SECONDARY_SELECT;
    }
}
void ChipDeselect(bool primaryFlag)
{
    if (primaryFlag)
    {
        SLAVE_PRIMARY_DESELECT;
    }
    else
    {
        SLAVE_SECONDARY_DESELECT;
    }
}

bool eeprom_addr_is_ok(uint16_t address)
{
    return ((address >= MIN_AVAIL_ADDR) && (address <= MAX_AVAIL_ADDR));
}

void write_eeprom_byte(uint16_t address, uint8_t byte, bool primaryFlag) //写入字节
{
    ChipSelect(primaryFlag);
    SPI_tradeByte(WREN);
    ChipDeselect(primaryFlag);
    ChipSelect(primaryFlag);
    SPI_tradeByte(WRITE);
    EEPROM_send16BitAddress(address);
    SPI_tradeByte(byte);
    ChipDeselect(primaryFlag);
    while (EEPROM_readStatus(primaryFlag) & _BV(EEPROM_WRITE_IN_PROGRESS))
    {
        ;
    }
}

void write_eeprom_array(uint16_t address,
                        uint8_t *buffer,
                        uint8_t sizeOfBuffer,
                        bool primaryFlag)
{
    ChipSelect(primaryFlag);
    SPI_tradeByte(WREN);
    ChipDeselect(primaryFlag);
    ChipSelect(primaryFlag);
    SPI_tradeByte(WRITE);
    EEPROM_send16BitAddress(address);

    for (uint8_t i = 0; i < sizeOfBuffer; i++)
    {
        SPI_tradeByte(buffer[i]);
    }
    ChipDeselect(primaryFlag);
    while (EEPROM_readStatus(primaryFlag) & _BV(EEPROM_WRITE_IN_PROGRESS))
    {
        ;
    }
}

uint8_t read_eeprom_byte(uint16_t address, bool primaryFlag) //读取字节函数
{
    ChipSelect(primaryFlag);
    SPI_tradeByte(READ);
    EEPROM_send16BitAddress(address);
    SPI_tradeByte(0);
    ChipDeselect(primaryFlag);
    return (SPDR);
}

char *read_eeprom_array(uint16_t address, //读取数组函数
                        uint8_t *buffer,
                        uint8_t sizeOfBuffer,
                        bool primaryFlag) //主次选择
{
    ChipSelect(primaryFlag);
    SPI_tradeByte(READ);
    EEPROM_send16BitAddress(address);
    for (uint8_t i = 0; i < sizeOfBuffer; i++)
    {
        SPI_tradeByte(0);
        *buffer++ = SPDR;
    }
    ChipDeselect(primaryFlag);
    return buffer;
}

uint8_t EEPROM_readStatus(bool primaryFlag)
{
    ChipSelect(primaryFlag);
    SPI_tradeByte(RDSR);
    SPI_tradeByte(0);
    ChipDeselect(primaryFlag);
    return (SPDR);
}

void SPI_tradeByte(uint8_t byte)
{
    SPDR = byte;
    loop_until_bit_is_set(SPSR, SPIF);
}

void EEPROM_send16BitAddress(uint16_t address)
{
    SPI_tradeByte((uint8_t)(address >> 8));
    SPI_tradeByte((uint8_t)address);
}
void InitializeEEProm(void)
{
    display.clearDisplay();
    display.drawBitmap(0, Y10, hui_16x16, ZH1_WIDTH, ZH1_HIGH, WHITE);
    display.drawBitmap(16, Y10, fu_16x16, ZH1_WIDTH, ZH1_HIGH, WHITE);
    display.drawBitmap(32, Y10, chuchang1_16x16, ZH1_WIDTH, ZH1_HIGH, WHITE);
    display.drawBitmap(48, Y10, chuchang2_16x16, ZH1_WIDTH, ZH1_HIGH, WHITE);
    display.drawBitmap(64, Y10, zhong_16x16, ZH1_WIDTH, ZH1_HIGH, WHITE);
    display.setCursor(80, 3);
    display.print("...");
    display.display();
    uint16_t pageAddress = MIN_AVAIL_ADDR;
    while (pageAddress <= MAX_AVAIL_ADDR)
    {
        SLAVE_PRIMARY_SELECT;
        SPI_tradeByte(WREN);
        SLAVE_PRIMARY_DESELECT;
        SLAVE_PRIMARY_SELECT;
        SPI_tradeByte(WRITE);
        EEPROM_send16BitAddress(pageAddress);
        for (uint8_t y = 0; y < EEPROM_BYTES_PER_PAGE; y++)
        {
            SPI_tradeByte(INITIAL_MEMORY_STATE_BYTE);
        }
        SLAVE_PRIMARY_DESELECT;
        pageAddress += EEPROM_BYTES_PER_PAGE;
        while (EEPROM_readStatus(true) & _BV(EEPROM_WRITE_IN_PROGRESS))
        {
            ;
        }
    }

    ///////////////
    write_eeprom_array(EEPROM_MARK_ADDR, Mark, EEPROM_MARK_SIZE, primaryFlag);
    write_eeprom_byte(SET_SHOW_PASSWORD_ADDR, 1, primaryFlag);
    showPassword[0] = 1;
    write_eeprom_byte(SET_READ_SERLAI_ADDR, 0, primaryFlag);
    readSerial[0] = 0;
    loginFailures[0] = 255;
    display.clearDisplay();
    display.drawBitmap(0, Y10, hui_16x16, ZH1_WIDTH, ZH1_HIGH, WHITE);
    display.drawBitmap(16, Y10, fu_16x16, ZH1_WIDTH, ZH1_HIGH, WHITE);
    display.drawBitmap(32, Y10, chuchang1_16x16, ZH1_WIDTH, ZH1_HIGH, WHITE);
    display.drawBitmap(48, Y10, chuchang2_16x16, ZH1_WIDTH, ZH1_HIGH, WHITE);
    display.drawBitmap(64, Y10, wan_16x16, ZH1_WIDTH, ZH1_HIGH, WHITE);
    display.drawBitmap(80, Y10, cheng_16x16, ZH1_WIDTH, ZH1_HIGH, WHITE);
    display.display();
    out();
}
////////////////////////以上代码修改自Daniel J. Murphy的PasswordPump///////////////////////////////

void CopyChip(bool restoreFlag)
{
    uint8_t buf[EEPROM_BYTES_PER_PAGE];
    for (uint16_t alladdress = MIN_AVAIL_ADDR;
         alladdress < MAX_AVAIL_ADDR;
         alladdress += EEPROM_BYTES_PER_PAGE)
    {
        read_eeprom_array(alladdress, buf, EEPROM_BYTES_PER_PAGE, restoreFlag);
        write_eeprom_array(alladdress, buf, EEPROM_BYTES_PER_PAGE, !restoreFlag);
    }
}


void menu()
{

    if (event != EVENT_NONE)
    {
        oldTime = millis();
        if ((menuID == EDIT_MODE) || (menuID == MENU_WELCOME))
        {
            edit();
        }
        else
        {

            if (event == EVENT_SINGLE_CLICK)
            {
                single_click();
            }

            if (event == EVENT_LONG_CLICK)
            {
                long_click();
            }

            if (event == EVENT_ROTATE_CW)
            {
                cw();
            }

            if (event == EVENT_ROTATE_CC)
            {
                cc();
            }
        }
        event = EVENT_NONE;
        my_display();
    }
    else
    {
    }
}

void edit()
{
    menuID = EDIT_MODE;

    if (event == EVENT_ROTATE_CW)
    {
        allChars_position++;
        if (allChars_position > ALLCHARS_SIZE)
        {
            allChars_position = 0;
        }
    }
    else if (event == EVENT_ROTATE_CC)
    {
        allChars_position--;
        if (allChars_position < 0)
        {
            allChars_position = ALLCHARS_SIZE;
        }
    }
    else if (event == EVENT_SINGLE_CLICK)
    {
        acconut_buffer[allChars_enterPosition] = allChars[allChars_position];
        allChars_enterPosition++;
        if (allChars_enterPosition > MASTER_PASSWORD_SIZE)
        {
            return false;
        }
    }
    else if (event == EVENT_LONG_CLICK)
    {
        if (LOCK)
        {

            read_eeprom_array(MASTER_PASSWORD_ADDR, masterPassword, MASTER_PASSWORD_SIZE, primaryFlag);
            if (loginFailures[0] == 255)
            {
                write_eeprom_array(MASTER_PASSWORD_ADDR, acconut_buffer, MASTER_PASSWORD_SIZE, primaryFlag);
                LOCK = false;
                menuID = MENU_ACCOUNT;
                loginFailures[0] = 0;
                clearbuf();
            }
            else if (strcmp(masterPassword, acconut_buffer) == 0)
            {
                LOCK = false;
                menuID = MENU_ACCOUNT;
                loginFailures[0] = 0;
                clearbuf();
            }
            else
            {
                out();
                loginFailures[0]++;
                clearbuf();
            }
            write_eeprom_byte(LOGIN_FAILURES_ADDR, loginFailures[0], primaryFlag);
        }
        else
        {
            switch (cardmenuID)
            {
            case CARD_MENU_Edit_Remark:
            {
                write_eeprom_array(REMARK_ADDR, acconut_buffer, REMARK_SIZE, primaryFlag);
                menuID = MENU_ID;
            }
            break;
            case CARD_MENU_Edit_Password:
            {
                write_eeprom_array(PASSWORE_ADDR, acconut_buffer, PASSWORD_SIZE, primaryFlag);
                menuID = MENU_ID;
            }
            break;
            case CARD_MENU_Edit_Username:
            {
                write_eeprom_array(USERNAME_ADDR, acconut_buffer, USERNAME_SIZE, primaryFlag);
                menuID = MENU_ID;
            }
            break;
            case CARD_MENU_Edit_Creds:
            {
                write_eeprom_array(ACCOUNT_ADDR, acconut_buffer, ACCOUNT_SIZE, primaryFlag);
                menuID = MENU_ID;
            }
            break;
            }
        }
    }
}

void single_click()
{
    clearbuf();
    if (menuID == MENU_ACCOUNT)
    {
        menuID = MENU_ACCOUNT_LIST;
    }
    else if (menuID == MENU_ACCOUNT_LIST)
    {
        menuID = MENU_ID;
    }
    else if (menuID == MENU_LOGOUT)
    {
        out();
    }
    else if (menuID == MENU_FACTORY_RESET)
    {
        confirmMark = false;
        menuID = MENU_SET_FACTORY_RESET;
    }
    else if (menuID == MENU_ID)
    {
        switch (cardmenuID)
        {
        case CARD_MENU_Delete_Acct:
        {
        }
        break;
        case CARD_MENU_Edit_Indicate_Style:
        {
            mode[0] = !mode[0];
            write_eeprom_byte(MODE_ADDR, mode[0], primaryFlag);
        }
        break;
        case CARD_MENU_Edit_Remark:
        case CARD_MENU_Edit_Password:
        case CARD_MENU_Edit_Username:
        case CARD_MENU_Edit_Creds:
        {
            menuID = EDIT_MODE;
        }
        break;
        case CARD_MENU_Send_User_Pass:
        {
            sendUsername();
            sendKEY();
            sendPassword();
        }
        break;
        case CARD_MENU_Send_Username:
        {
            sendUsername();
        }
        break;
        case CARD_MENU_Send_Password:
        {
            sendPassword();
        }
        break;
        case CARD_MENU_Send_Remark:
        {
            sendRemark();
        }
        break;
        }
    }
}

void long_click()
{
    if (menuID == MENU_SHOW_PASSWORD)
    {
        showPassword[0] = !showPassword[0];
        write_eeprom_byte(SET_SHOW_PASSWORD_ADDR, showPassword[0], primaryFlag);
    }
    else if (menuID == MENU_READ_SERLAI)
    {
        readSerial[0] = !readSerial[0];
        write_eeprom_byte(SET_READ_SERLAI_ADDR, readSerial[0], primaryFlag);
    }
    else if (menuID == MENU_BACKUP_EEPROM)
    {
        display.clearDisplay();
        menuID = MENU_BACKUP_ON;
        my_display();
        CopyChip(true);
        display.clearDisplay();
        menuID = MENU_BACKUP_END;
        my_display();
    }
    else if (menuID == MENU_BACKUP_FILE)
    {
        display.clearDisplay();
        menuID = MENU_BACKUP_ON;
        my_display();
        sendAll();
        display.clearDisplay();
        menuID = MENU_BACKUP_END;
        my_display();
    }
    else if (menuID == MENU_RESTORE_BACKUP)
    {
        display.clearDisplay();
        menuID = MENU_RESTORE_ON;
        my_display();
        CopyChip(false);
        display.clearDisplay();
        menuID = MENU_RESTORE_END;
        my_display();
    }

    else if (menuID == MENU_SET_FACTORY_RESET)
    {
        if (confirmMark)
        {
            InitializeEEProm();
        }
        else
        {
            menuID = MENU_ACCOUNT;
        }
    }
    else if (menuID > 10)
    {
        menuID = menuID / 10;
    }
    else if ((menuID == MENU_ID) || (cardmenuID == CARD_MENU_Delete_Acct))
    {
        uint8_t empty[IDs_SIZE];
        for (uint8_t i = 0; i < IDs_SIZE; i++)
        {
            empty[i] = NULL_TERM;
        }
        write_eeprom_array(ACCOUNT_ADDR, empty, IDs_SIZE, primaryFlag);
        menuID = MENU_ID;
    }
}

void cw()
{
    if (menuID == MENU_ID)
    {
        cardmenuID++;
        if (cardmenuID > CARD_MENU_MAX)
        {
            cardmenuID = CARD_MENU_MIN;
        }
    }
    else if (menuID < MAIN_MENU_MAX)
    {
        menuID++;
    }
    else if (menuID == MENU_ACCOUNT_LIST)
    {
        IDs++;
        if (IDs > IDs_MAX)
        {
            IDs = IDs_MIN;
        }
    }
    else if (menuID == MENU_SET_FACTORY_RESET)
    {
        confirmMark = !confirmMark;
    }
    else if (menuID == MENU_WELCOME)
    {
        menuID == EDIT_MODE;
    }
}

void cc()
{
    if (menuID == MENU_ID)
    {
        cardmenuID--;
        if (cardmenuID < CARD_MENU_MIN)
        {
            cardmenuID = CARD_MENU_MAX;
        }
    }
    else if ((menuID > MAIN_MENU_MIN) && (menuID <= MAIN_MENU_MAX))
    {
        menuID--;
    }
    else if (menuID == MENU_ACCOUNT_LIST)
    {
        IDs--;
        if (IDs < IDs_MIN)
        {
            IDs = IDs_MAX;
        }
    }
    else if (menuID == MENU_SET_FACTORY_RESET)
    {
        confirmMark = !confirmMark;
    }
    else if (menuID == MENU_WELCOME)
    {
        menuID == EDIT_MODE;
    }
}

void my_display()
{

    display.setTextSize(1); // 字体大小
    display.setTextColor(WHITE);
    display.setTextWrap(0); //关闭换行

    switch (menuID)
    {
    case EDIT_MODE:
    {
        if (LOCK)
        {
            int i = 0;
            display.drawBitmap(X10 + (ZH1_WIDTH * i), Y10, mi_16x16, ZH1_WIDTH, ZH1_HIGH, WHITE);
            i++;
            display.drawBitmap(X10 + (ZH1_WIDTH * i), Y10, ma_16x16, ZH1_WIDTH, ZH1_HIGH, WHITE);
        }
        display.setCursor(0, 24);
        if (showPassword[0])
        {
            display.print(acconut_buffer);
        }
        display.setTextSize(2);
        display.setCursor(112, 1);
        display.print(allChars[allChars_position]);
    }
    break;
    case MENU_ACCOUNT:
    {
        int i = 0;
        display.drawBitmap(X10 + (ZH1_WIDTH * i), Y10, zhang_16x16, ZH1_WIDTH, ZH1_HIGH, WHITE);
        i++;
        display.drawBitmap(X10 + (ZH1_WIDTH * i), Y10, hu_16x16, ZH1_WIDTH, ZH1_HIGH, WHITE);
    }
    break;
    case MENU_LOGOUT:
    {
        int i = 0;
        display.drawBitmap(X10 + (ZH1_WIDTH * i), Y10, zhu_16x16, ZH1_WIDTH, ZH1_HIGH, WHITE);
        i++;
        display.drawBitmap(X10 + (ZH1_WIDTH * i), Y10, xiao_16x16, ZH1_WIDTH, ZH1_HIGH, WHITE);
    }
    break;
    case MENU_READ_SERLAI:
    {
        int i = 0;
        display.drawBitmap(X10 + (ZH1_WIDTH * i), Y10, chuan_16x16, ZH1_WIDTH, ZH1_HIGH, WHITE);
        i++;
        display.drawBitmap(X10 + (ZH1_WIDTH * i), Y10, kou_16x16, ZH1_WIDTH, ZH1_HIGH, WHITE);
        readSerial[0] = read_eeprom_byte(SET_READ_SERLAI_ADDR, primaryFlag);
        if (readSerial[0])
        {
            display.drawBitmap(X_YES, Y_YES, kai_12x12, ZH2_WIDTH, ZH2_HIGH, WHITE);
        }
        else
        {
            display.drawBitmap(X_YES, Y_YES, guan_12x12, ZH2_WIDTH, ZH2_HIGH, WHITE);
        }
    }
    break;
    case MENU_SHOW_PASSWORD:
    {
        int i = 0;
        display.drawBitmap(X10 + (ZH1_WIDTH * i), Y10, xian_16x16, ZH1_WIDTH, ZH1_HIGH, WHITE);
        i++;
        display.drawBitmap(X10 + (ZH1_WIDTH * i), Y10, shi_16x16, ZH1_WIDTH, ZH1_HIGH, WHITE);
        i++;
        display.drawBitmap(X10 + (ZH1_WIDTH * i), Y10, mi_16x16, ZH1_WIDTH, ZH1_HIGH, WHITE);
        i++;
        display.drawBitmap(X10 + (ZH1_WIDTH * i), Y10, ma_16x16, ZH1_WIDTH, ZH1_HIGH, WHITE);
        showPassword[0] = read_eeprom_byte(SET_SHOW_PASSWORD_ADDR, primaryFlag);
        if (showPassword[0])
        {
            display.drawBitmap(X_YES, Y_YES, kai_12x12, ZH2_WIDTH, ZH2_HIGH, WHITE);
        }
        else
        {
            display.drawBitmap(X_YES, Y_YES, guan_12x12, ZH2_WIDTH, ZH2_HIGH, WHITE);
        }
    }
    break;
    case MENU_BACKUP_EEPROM:
    {
        int i = 0;
        display.drawBitmap(X10 + (ZH1_WIDTH * i), Y10, bei_16x16, ZH1_WIDTH, ZH1_HIGH, WHITE);
        i++;
        display.drawBitmap(X10 + (ZH1_WIDTH * i), Y10, fen_16x16, ZH1_WIDTH, ZH1_HIGH, WHITE);
        i++;
        display.drawBitmap(X10 + (ZH1_WIDTH * i), Y10, dao_16x16, ZH1_WIDTH, ZH1_HIGH, WHITE);
        i++;
        display.setCursor((ZH1_WIDTH * i), (ZH1_HIGH - 8));
        display.print("EEPROM");
    }
    break;
    case MENU_BACKUP_ON:
    {
        int i = 0;
        display.drawBitmap(X10 + (ZH1_WIDTH * i), Y10, bei_16x16, ZH1_WIDTH, ZH1_HIGH, WHITE);
        i++;
        display.drawBitmap(X10 + (ZH1_WIDTH * i), Y10, fen_16x16, ZH1_WIDTH, ZH1_HIGH, WHITE);
        i++;
        display.drawBitmap(X10 + (ZH1_WIDTH * i), Y10, zhong_16x16, ZH1_WIDTH, ZH1_HIGH, WHITE);
        i++;
        display.setCursor((ZH1_WIDTH * i), (ZH1_HIGH - 8));
        display.print("...");
    }
    break;
    case MENU_BACKUP_END:
    {
        int i = 0;
        display.drawBitmap(X10 + (ZH1_WIDTH * i), Y10, bei_16x16, ZH1_WIDTH, ZH1_HIGH, WHITE);
        i++;
        display.drawBitmap(X10 + (ZH1_WIDTH * i), Y10, fen_16x16, ZH1_WIDTH, ZH1_HIGH, WHITE);
        i++;
        display.drawBitmap(X10 + (ZH1_WIDTH * i), Y10, wan_16x16, ZH1_WIDTH, ZH1_HIGH, WHITE);
        i++;
        display.drawBitmap(X10 + (ZH1_WIDTH * i), Y10, cheng_16x16, ZH1_WIDTH, ZH1_HIGH, WHITE);
    }
    break;
    case MENU_BACKUP_FILE:
    {
        int i = 0;
        display.drawBitmap(X10 + (ZH1_WIDTH * i), Y10, bei_16x16, ZH1_WIDTH, ZH1_HIGH, WHITE);
        i++;
        display.drawBitmap(X10 + (ZH1_WIDTH * i), Y10, fen_16x16, ZH1_WIDTH, ZH1_HIGH, WHITE);
        i++;
        display.drawBitmap(X10 + (ZH1_WIDTH * i), Y10, dao_16x16, ZH1_WIDTH, ZH1_HIGH, WHITE);
        i++;
        display.setCursor((ZH1_WIDTH * i), (ZH1_HIGH - 8));
        display.print("FILE");
    }
    break;
    case MENU_RESTORE_BACKUP:
    {
        int i = 0;
        display.drawBitmap(X10 + (ZH1_WIDTH * i), Y10, hui_16x16, ZH1_WIDTH, ZH1_HIGH, WHITE);
        i++;
        display.drawBitmap(X10 + (ZH1_WIDTH * i), Y10, fu_16x16, ZH1_WIDTH, ZH1_HIGH, WHITE);
        i++;
        display.drawBitmap(X10 + (ZH1_WIDTH * i), Y10, bei_16x16, ZH1_WIDTH, ZH1_HIGH, WHITE);
        i++;
        display.drawBitmap(X10 + (ZH1_WIDTH * i), Y10, fen_16x16, ZH1_WIDTH, ZH1_HIGH, WHITE);
    }
    break;

    case MENU_RESTORE_ON:
    {
        int i = 0;
        display.drawBitmap(X10 + (ZH1_WIDTH * i), Y10, hui_16x16, ZH1_WIDTH, ZH1_HIGH, WHITE);
        i++;
        display.drawBitmap(X10 + (ZH1_WIDTH * i), Y10, fu_16x16, ZH1_WIDTH, ZH1_HIGH, WHITE);
        i++;
        display.drawBitmap(X10 + (ZH1_WIDTH * i), Y10, zhong_16x16, ZH1_WIDTH, ZH1_HIGH, WHITE);
        i++;
        display.setCursor((ZH1_WIDTH * i), (ZH1_HIGH - 8));
        display.print("...");
    }
    break;
    case MENU_RESTORE_END:
    {
        int i = 0;
        display.drawBitmap(X10 + (ZH1_WIDTH * i), Y10, hui_16x16, ZH1_WIDTH, ZH1_HIGH, WHITE);
        i++;
        display.drawBitmap(X10 + (ZH1_WIDTH * i), Y10, fu_16x16, ZH1_WIDTH, ZH1_HIGH, WHITE);
        i++;
        display.drawBitmap(X10 + (ZH1_WIDTH * i), Y10, wan_16x16, ZH1_WIDTH, ZH1_HIGH, WHITE);
        i++;
        display.drawBitmap(X10 + (ZH1_WIDTH * i), Y10, cheng_16x16, ZH1_WIDTH, ZH1_HIGH, WHITE);
    }
    break;
    case MENU_FACTORY_RESET:
    {
        int i = 0;
        display.drawBitmap(X10 + (ZH1_WIDTH * i), Y10, hui_16x16, ZH1_WIDTH, ZH1_HIGH, WHITE);
        i++;
        display.drawBitmap(X10 + (ZH1_WIDTH * i), Y10, fu_16x16, ZH1_WIDTH, ZH1_HIGH, WHITE);
        i++;
        display.drawBitmap(X10 + (ZH1_WIDTH * i), Y10, chuchang1_16x16, ZH1_WIDTH, ZH1_HIGH, WHITE);
        i++;
        display.drawBitmap(X10 + (ZH1_WIDTH * i), Y10, chuchang2_16x16, ZH1_WIDTH, ZH1_HIGH, WHITE);
    }
    break;
    case MENU_ACCOUNT_LIST:
    {
        display.setCursor(92, 0);
        display.setTextColor(WHITE);
        display.setTextSize(1);
        display.print("ID:");
        display.println(IDs);

        if ((read_eeprom_byte(ACCOUNT_ADDR, primaryFlag) == 255) && (read_eeprom_byte(USERNAME_ADDR, primaryFlag) == 255) && (read_eeprom_byte(PASSWORE_ADDR, primaryFlag) == 255) && (read_eeprom_byte(REMARK_ADDR, primaryFlag) == 255))
        {
            display.drawBitmap(56, Y20, kong_16x16, ZH1_WIDTH, ZH1_HIGH, WHITE);
        }
        else
        {
            read_eeprom_array(ACCOUNT_ADDR, accountName, ACCOUNT_SIZE, primaryFlag);
            display.setTextSize(2);
            display.setCursor(X20, Y20);
            display.print(accountName);
        }
    }
    break;
    case MENU_WELCOME:
    {
        display.drawBitmap(0, 0, welcome_128x32, 128, 32, WHITE);
    }
    break;

    case MENU_SET_FACTORY_RESET:
    {
        int i = 0;
        display.drawBitmap(X10 + (ZH1_WIDTH * i), Y10, hui_16x16, ZH1_WIDTH, ZH1_HIGH, WHITE);
        i++;
        display.drawBitmap(X10 + (ZH1_WIDTH * i), Y10, fu_16x16, ZH1_WIDTH, ZH1_HIGH, WHITE);
        i++;
        display.drawBitmap(X10 + (ZH1_WIDTH * i), Y10, chuchang1_16x16, ZH1_WIDTH, ZH1_HIGH, WHITE);
        i++;
        display.drawBitmap(X10 + (ZH1_WIDTH * i), Y10, chuchang2_16x16, ZH1_WIDTH, ZH1_HIGH, WHITE);
        i++;
        display.setCursor(X10 + (ZH1_WIDTH * i), 1);
        display.setTextSize(2);
        display.print("!!!");
        if (confirmMark)
        {
            display.drawBitmap(X_YES, Y_YES, yes_12x12, ZH2_WIDTH, ZH2_HIGH, WHITE);
        }
        else
        {
            display.drawBitmap(X_YES, Y_YES, no_12x12, ZH2_WIDTH, ZH2_HIGH, WHITE);
        }
    }
    break;
    case MENU_ID:
    {
        display.setCursor(0, 22);
        display.setTextColor(WHITE);
        display.setTextSize(1);
        display.print("ID:");
        display.println(IDs);
        switch (cardmenuID)
        {
        case CARD_MENU_Delete_Acct:
        {
            int i = 4;
            display.drawBitmap(SCREEN_WIDTH - (ZH2_WIDTH * i), Y_YES, shan_12x12, ZH2_WIDTH, ZH2_HIGH, WHITE);
            i--;
            display.drawBitmap(SCREEN_WIDTH - (ZH2_WIDTH * i), Y_YES, chu_12x12, ZH2_WIDTH, ZH2_HIGH, WHITE);
            i--;
            display.drawBitmap(SCREEN_WIDTH - (ZH2_WIDTH * i), Y_YES, zhang_12x12, ZH2_WIDTH, ZH2_HIGH, WHITE);
            i--;
            display.drawBitmap(SCREEN_WIDTH - (ZH2_WIDTH * i), Y_YES, hu_12x12, ZH2_WIDTH, ZH2_HIGH, WHITE);
        }
        break;

        case CARD_MENU_Edit_Indicate_Style:
        {
            int i = 6;
            display.drawBitmap(SCREEN_WIDTH - (ZH2_WIDTH * i), Y_YES, bian_12x12, ZH2_WIDTH, ZH2_HIGH, WHITE);
            i--;
            display.drawBitmap(SCREEN_WIDTH - (ZH2_WIDTH * i), Y_YES, ji_12x12, ZH2_WIDTH, ZH2_HIGH, WHITE);
            i--;
            display.drawBitmap(SCREEN_WIDTH - (ZH2_WIDTH * i), Y_YES, fa_12x12, ZH2_WIDTH, ZH2_HIGH, WHITE);
            i--;
            display.drawBitmap(SCREEN_WIDTH - (ZH2_WIDTH * i), Y_YES, song_12x12, ZH2_WIDTH, ZH2_HIGH, WHITE);
            i--;
            display.drawBitmap(SCREEN_WIDTH - (ZH2_WIDTH * i), Y_YES, mo_12x12, ZH2_WIDTH, ZH2_HIGH, WHITE);
            i--;
            display.drawBitmap(SCREEN_WIDTH - (ZH2_WIDTH * i), Y_YES, shi_12x12, ZH2_WIDTH, ZH2_HIGH, WHITE);
            display.setCursor(0, 0);
            mode[0] = read_eeprom_byte(MODE_ADDR, primaryFlag);
            if (mode[0])
            {
                display.print("Tab");
            }
            else
            {
                display.print("Enter");
            }
        }
        break;

        case CARD_MENU_Edit_Remark:
        {
            int i = 4;
            display.drawBitmap(SCREEN_WIDTH - (ZH2_WIDTH * i), Y_YES, bian_12x12, ZH2_WIDTH, ZH2_HIGH, WHITE);
            i--;
            display.drawBitmap(SCREEN_WIDTH - (ZH2_WIDTH * i), Y_YES, ji_12x12, ZH2_WIDTH, ZH2_HIGH, WHITE);
            i--;
            display.drawBitmap(SCREEN_WIDTH - (ZH2_WIDTH * i), Y_YES, bei_12x12, ZH2_WIDTH, ZH2_HIGH, WHITE);
            i--;
            display.drawBitmap(SCREEN_WIDTH - (ZH2_WIDTH * i), Y_YES, zhu_12x12, ZH2_WIDTH, ZH2_HIGH, WHITE);
            display.setCursor(0, 0);
            read_eeprom_array(REMARK_ADDR, remark, REMARK_SIZE, primaryFlag);
            display.print(remark);
        }
        break;

        case CARD_MENU_Edit_Password:
        {
            int i = 4;
            display.drawBitmap(SCREEN_WIDTH - (ZH2_WIDTH * i), Y_YES, bian_12x12, ZH2_WIDTH, ZH2_HIGH, WHITE);
            i--;
            display.drawBitmap(SCREEN_WIDTH - (ZH2_WIDTH * i), Y_YES, ji_12x12, ZH2_WIDTH, ZH2_HIGH, WHITE);
            i--;
            display.drawBitmap(SCREEN_WIDTH - (ZH2_WIDTH * i), Y_YES, mi_12x12, ZH2_WIDTH, ZH2_HIGH, WHITE);
            i--;
            display.drawBitmap(SCREEN_WIDTH - (ZH2_WIDTH * i), Y_YES, ma_12x12, ZH2_WIDTH, ZH2_HIGH, WHITE);
            if (showPassword[0])
            {
                display.setCursor(0, 0);
                read_eeprom_array(PASSWORE_ADDR, password, PASSWORD_SIZE, primaryFlag);
                display.print(password);
            }
        }
        break;

        case CARD_MENU_Edit_Username:
        {
            int i = 5;
            display.drawBitmap(SCREEN_WIDTH - (ZH2_WIDTH * i), Y_YES, bian_12x12, ZH2_WIDTH, ZH2_HIGH, WHITE);
            i--;
            display.drawBitmap(SCREEN_WIDTH - (ZH2_WIDTH * i), Y_YES, ji_12x12, ZH2_WIDTH, ZH2_HIGH, WHITE);
            i--;
            display.drawBitmap(SCREEN_WIDTH - (ZH2_WIDTH * i), Y_YES, yong_12x12, ZH2_WIDTH, ZH2_HIGH, WHITE);
            i--;
            display.drawBitmap(SCREEN_WIDTH - (ZH2_WIDTH * i), Y_YES, hu_12x12, ZH2_WIDTH, ZH2_HIGH, WHITE);
            i--;
            display.drawBitmap(SCREEN_WIDTH - (ZH2_WIDTH * i), Y_YES, ming_12x12, ZH2_WIDTH, ZH2_HIGH, WHITE);
            display.setCursor(0, 0);
            read_eeprom_array(USERNAME_ADDR, username, USERNAME_SIZE, primaryFlag);
            display.print(username);
        }
        break;

        case CARD_MENU_Edit_Creds:
        {
            int i = 4;
            display.drawBitmap(SCREEN_WIDTH - (ZH2_WIDTH * i), Y_YES, bian_12x12, ZH2_WIDTH, ZH2_HIGH, WHITE);
            i--;
            display.drawBitmap(SCREEN_WIDTH - (ZH2_WIDTH * i), Y_YES, ji_12x12, ZH2_WIDTH, ZH2_HIGH, WHITE);
            i--;
            display.drawBitmap(SCREEN_WIDTH - (ZH2_WIDTH * i), Y_YES, biao_12x12, ZH2_WIDTH, ZH2_HIGH, WHITE);
            i--;
            display.drawBitmap(SCREEN_WIDTH - (ZH2_WIDTH * i), Y_YES, ti_12x12, ZH2_WIDTH, ZH2_HIGH, WHITE);
            display.setCursor(0, 0);
            read_eeprom_array(ACCOUNT_ADDR, accountName, ACCOUNT_SIZE, primaryFlag);
            display.print(accountName);
        }
        break;

        case CARD_MENU_Send_User_Pass:
        {
            int i = 7;
            display.drawBitmap(SCREEN_WIDTH - (ZH2_WIDTH * i), Y_YES, fa_12x12, ZH2_WIDTH, ZH2_HIGH, WHITE);
            i--;
            display.drawBitmap(SCREEN_WIDTH - (ZH2_WIDTH * i), Y_YES, yong_12x12, ZH2_WIDTH, ZH2_HIGH, WHITE);
            i--;
            display.drawBitmap(SCREEN_WIDTH - (ZH2_WIDTH * i), Y_YES, hu_12x12, ZH2_WIDTH, ZH2_HIGH, WHITE);
            i--;
            display.drawBitmap(SCREEN_WIDTH - (ZH2_WIDTH * i), Y_YES, ming_12x12, ZH2_WIDTH, ZH2_HIGH, WHITE);
            i--;
            display.drawBitmap(SCREEN_WIDTH - (ZH2_WIDTH * i), Y_YES, he_12x12, ZH2_WIDTH, ZH2_HIGH, WHITE);
            i--;
            display.drawBitmap(SCREEN_WIDTH - (ZH2_WIDTH * i), Y_YES, mi_12x12, ZH2_WIDTH, ZH2_HIGH, WHITE);
            i--;
            display.drawBitmap(SCREEN_WIDTH - (ZH2_WIDTH * i), Y_YES, ma_12x12, ZH2_WIDTH, ZH2_HIGH, WHITE);
            display.setCursor(0, 0);
            read_eeprom_array(ACCOUNT_ADDR, accountName, ACCOUNT_SIZE, primaryFlag);
            display.print(accountName);
        }
        break;

        case CARD_MENU_Send_Username:
        {
            int i = 5;
            display.drawBitmap(SCREEN_WIDTH - (ZH2_WIDTH * i), Y_YES, fa_12x12, ZH2_WIDTH, ZH2_HIGH, WHITE);
            i--;
            display.drawBitmap(SCREEN_WIDTH - (ZH2_WIDTH * i), Y_YES, song_12x12, ZH2_WIDTH, ZH2_HIGH, WHITE);
            i--;
            display.drawBitmap(SCREEN_WIDTH - (ZH2_WIDTH * i), Y_YES, yong_12x12, ZH2_WIDTH, ZH2_HIGH, WHITE);
            i--;
            display.drawBitmap(SCREEN_WIDTH - (ZH2_WIDTH * i), Y_YES, hu_12x12, ZH2_WIDTH, ZH2_HIGH, WHITE);
            i--;
            display.drawBitmap(SCREEN_WIDTH - (ZH2_WIDTH * i), Y_YES, ming_12x12, ZH2_WIDTH, ZH2_HIGH, WHITE);
            display.setCursor(0, 0);
            read_eeprom_array(USERNAME_ADDR, username, USERNAME_SIZE, primaryFlag);
            display.print(username);
        }
        break;

        case CARD_MENU_Send_Password:
        {
            int i = 4;
            display.drawBitmap(SCREEN_WIDTH - (ZH2_WIDTH * i), Y_YES, fa_12x12, ZH2_WIDTH, ZH2_HIGH, WHITE);
            i--;
            display.drawBitmap(SCREEN_WIDTH - (ZH2_WIDTH * i), Y_YES, song_12x12, ZH2_WIDTH, ZH2_HIGH, WHITE);
            i--;
            display.drawBitmap(SCREEN_WIDTH - (ZH2_WIDTH * i), Y_YES, mi_12x12, ZH2_WIDTH, ZH2_HIGH, WHITE);
            i--;
            display.drawBitmap(SCREEN_WIDTH - (ZH2_WIDTH * i), Y_YES, ma_12x12, ZH2_WIDTH, ZH2_HIGH, WHITE);

            if (showPassword[0])
            {
                display.setCursor(0, 0);
                read_eeprom_array(PASSWORE_ADDR, password, PASSWORD_SIZE, primaryFlag);
                display.print(password);
            }
        }
        break;

        case CARD_MENU_Send_Remark:
        {
            int i = 4;
            display.drawBitmap(SCREEN_WIDTH - (ZH2_WIDTH * i), Y_YES, fa_12x12, ZH2_WIDTH, ZH2_HIGH, WHITE);
            i--;
            display.drawBitmap(SCREEN_WIDTH - (ZH2_WIDTH * i), Y_YES, song_12x12, ZH2_WIDTH, ZH2_HIGH, WHITE);
            i--;
            display.drawBitmap(SCREEN_WIDTH - (ZH2_WIDTH * i), Y_YES, bei_12x12, ZH2_WIDTH, ZH2_HIGH, WHITE);
            i--;
            display.drawBitmap(SCREEN_WIDTH - (ZH2_WIDTH * i), Y_YES, zhu_12x12, ZH2_WIDTH, ZH2_HIGH, WHITE);
            i--;
            display.setCursor(0, 0);
            read_eeprom_array(REMARK_ADDR, remark, REMARK_SIZE, primaryFlag);
            display.print(remark);
        }
        break;
        }
    }
    break;
    }
    display.display();
}

void sendAccountName()
{
    read_eeprom_array(ACCOUNT_ADDR, accountName, ACCOUNT_SIZE, primaryFlag);
    Keyboard.begin();
    Keyboard.print(accountName);
    Keyboard.end();
}
void sendUsername()
{
    read_eeprom_array(USERNAME_ADDR, username, USERNAME_SIZE, primaryFlag);
    Keyboard.begin();
    Keyboard.print(username);
    Keyboard.end();
}

void sendPassword()
{
    read_eeprom_array(PASSWORE_ADDR, password, PASSWORD_SIZE, primaryFlag);
    Keyboard.begin();
    Keyboard.print(password);
    Keyboard.end();
}
void sendRemark()
{
    read_eeprom_array(REMARK_ADDR, remark, REMARK_SIZE, primaryFlag);
    Keyboard.begin();
    Keyboard.print(remark);
    Keyboard.end();
}

void sendKEY()
{
    if (mode[0])
    {
        Keyboard.begin();
        Keyboard.press(KEY_TAB);
        Keyboard.release(KEY_TAB);
        Keyboard.end();
    }
    else
    {
        Keyboard.write('\n');
    }
}

void sendAll()
{
    for (IDs = 0; IDs < IDs_MAX; IDs++)
    {
        Keyboard.begin();
        Keyboard.print(IDs);
        Keyboard.write('\n');
        sendAccountName();
        Keyboard.write('\n');
        sendUsername();
        Keyboard.write('\n');
        sendPassword();
        Keyboard.write('\n');
        sendRemark();
        Keyboard.write('\n');
        Keyboard.end();
    }
}